#ifndef __CPIL_MEMORY_HPP__
#define __CPIL_MEMORY_HPP__

//#define __DEBUG_MEMORY__

#include <exception.hpp>
#include <countermemoryblock.hpp>

#ifdef __DEBUG_MEMORY__
    #include<iostream>
    using namespace std;
#endif

//! Shortcut to singleton
#define CPIL_MEMORY Memory::getInstance()


//TODO : revoir la gestion des singletons au sein de la memoire
// alloc auto faite par les define CSTE singleton.getInstance()
// mais pas de delete
// donc creer une gestion des singletons en block, tes les counters
// dailleurs a terme le faire pour les types de bases


class Memory
{
    private:

        CounterMemoryBlock countersBlock;
        #ifdef __DEBUG_MEMORY__
        int       balance;
        #endif

    protected:

        Memory();
        ~Memory();

        Memory(const Memory &);
        Memory& operator=(const Memory &);

    public:

        static Memory * getInstance();
        static void killInstance();

        template<typename T>
        inline T * newArray(unsigned int size)
        {
            #ifdef __DEBUG_MEMORY__
                balance++;
                cout<<"["<<balance<<"]"<<"Alloc Array"<<endl;
            #endif
            return new T[size];
        }

        template<typename T>
        inline void delArray(T *adr)
        {
            #ifdef __DEBUG_MEMORY__
                balance--;
                cout<<"["<<balance<<"]"<<"Delet Array"<<endl;
            #endif
            if( adr )
                delete [] adr;
        }

        Counter * newCounter();
        void      delCounter(Counter *);


    private:

        static Memory * _instance;
};

#endif
